﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using Hallenberg.Core;
using Hallenberg.SmartClient.Interfaces;
using Microsoft.Practices.EnterpriseLibrary.Common;
using System.Reflection;

namespace Hallenberg.SmartClient.Menu
{
    [DebuggerDisplay("{MenuItemName}, ChildItems = {ChildItems.Count}")]
    public class MenuItem
    {
        private string m_MenuItemTitle;
        private List<string> m_RequiredRoles;
        private List<string> m_RequiredUsers;

        public MenuItem Parent { get; set; }
        public string MenuItemName { get; private set; }

        public string ToolTip { get; private set; }
        public int SortIndex { get; set; }

        public ChildMenuItemsCollection ChildItems { get; set; }

        public MenuItemDisabledPolicy DisplayPolicy { get; private set; }
        public IPredicate CanExecuteEvaluator { get; set; }
        public IResourceMapper ResourceMapper { get; set; }

        public string AttachedToClass { get; set; }
        public string AttachedToMethod { get; internal set; }

        public string TitleResourceName { get; set; }
        public Type TitleResourceType { get; set; }

        public ReadOnlyCollection<string> RequiredRoles
        {
            get
            {
                return new ReadOnlyCollection<string>(m_RequiredRoles);
            }
        }

        public ReadOnlyCollection<string> RequiredUsers
        {
            get
            {
                return new ReadOnlyCollection<string>(m_RequiredUsers);
            }
        }

        public string MenuItemTitle
        {
            get
            {
                return TranslatedMenuTitle();
            }
            set
            {
                m_MenuItemTitle = value;
            }
        }

        public bool CanExecute
        {
            get
            {
                bool canExecute = true;

                if (RequiredRoles.Count() > 0)
                {
                    canExecute = RequiredRoles.Any(rr => Thread.CurrentPrincipal.IsInRole(rr));
                }

                if (canExecute && RequiredUsers.Count() > 0)
                {
                    canExecute = RequiredUsers.Any(ru => Thread.CurrentPrincipal.Identity.Name.Equals(ru, StringComparison.CurrentCulture));
                }

                if (canExecute && CanExecuteEvaluator != null && CanExecuteEvaluator.Evaluate())
                {
                    return true;
                }

                if (canExecute && CanExecuteEvaluator == null)
                {
                    return true;
                }

                return false;
            }
        }

        public bool IsReadOnly
        {
            get
            {
                return !CanExecute && DisplayPolicy == MenuItemDisabledPolicy.ReadOnly ? true : false;
            }
        }

        public bool IsVisible
        {
            get
            {
                return CanExecute && DisplayPolicy == MenuItemDisabledPolicy.Hide ? true : false;
            }
        }

        public MenuItem(string menuItemName, string menuItemTitle, string toolTip)
            : this(menuItemName, menuItemTitle, toolTip, MenuItemDisabledPolicy.Hide)
        {
        }

        public MenuItem(string menuItemName, string menuItemTitle, string toolTip, MenuItemDisabledPolicy displayPolicy)
        {
            m_RequiredRoles = new List<string>();
            m_RequiredUsers = new List<string>();

            MenuItemName = menuItemName;
            MenuItemTitle = menuItemTitle;
            ToolTip = toolTip;
            DisplayPolicy = displayPolicy;
            ChildItems = new ChildMenuItemsCollection();
            ResourceMapper = null;
        }

        public MenuItem FindMenuItem(string menuItemName)
        {
            Debug.Assert(!string.IsNullOrEmpty(menuItemName));
            if (string.IsNullOrEmpty(menuItemName))
            {
                throw new ArgumentNullException("menuItemName");
            }

            return ChildItems.FirstOrDefault(menu => (menu.MenuItemName == menuItemName));
        }

        public void AddRequiredRoles(string[] roles)
        {
            Debug.Assert(roles != null);
            if (roles == null)
            {
                throw new ArgumentNullException("roles");
            }

            m_RequiredRoles.AddRange(roles);
        }

        public void AddRequiredUsers(string[] users)
        {
            Debug.Assert(users != null);
            if (users == null)
            {
                throw new ArgumentNullException("users");
            }

            m_RequiredUsers.AddRange(users);
        }

        private string TranslatedMenuTitle()
        {
            if (!string.IsNullOrEmpty(this.TitleResourceName) && this.TitleResourceType != null)
            {
                return ResourceStringLoader.LoadString(
                    this.TitleResourceType.FullName, 
                    this.TitleResourceName, 
                    this.TitleResourceType.Assembly);
            }

            return m_MenuItemTitle;
        }
    }
}
